package com.lsh.oms.provider.service.payment;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.json.JsonUtils;
import com.lsh.base.common.model.CommonResult;
import com.lsh.base.lang.Exceptions;
import com.lsh.oms.api.model.es.OrderHeadForEs;
import com.lsh.oms.api.model.order.OrderReceiptPayNotifyDTO;
import com.lsh.oms.api.model.order.sign.OrderReceiptNotifyDTO;
import com.lsh.oms.api.service.payment.IReceiptPaymentNotifyRestService;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.enums.*;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.exception.ExceptionStatus;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.order.OrderShippingHead;
import com.lsh.oms.core.model.order.OrderShippingHeadWithBLOBs;
import com.lsh.oms.core.model.order.OrderSignHead;
import com.lsh.oms.core.proxy.handler.OrderConcurrentHandler;
import com.lsh.oms.core.proxy.service.EsProxy;
import com.lsh.oms.core.service.asynservice.OmsEventBus;
import com.lsh.oms.core.service.other.SignOrderService;
import com.lsh.oms.core.service.payment.PaymentService;
import com.lsh.oms.core.service.po.OmsTaskService;
import com.lsh.oms.core.utils.DateUtil;
import com.lsh.oms.provider.utils.ValidationBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.UUID;

/**
 * Project Name: OrderPaymentOnlineNotifyRestService
 * 北京链商电子商务有限公司
 *
 * @author peter
 * Date: 19/7/18
 * Package Name: com.lsh.oms.provider.service.payment
 * Description:订单在线支付,异步回调的接口
 */
@Service(protocol = "rest", timeout = 30000)
@Path("receipt/pay")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({ContentType.APPLICATION_JSON_UTF_8})
@Slf4j
public class ReceiptPayNotifyRestServiceImpl implements IReceiptPaymentNotifyRestService {

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private SignOrderService signOrderService;

    @Autowired
    private EsProxy esProxy;

    @Autowired
    private OmsTaskService omsTaskService;

    @POST
    @Path("tms/notify")
    @Override
    public CommonResult payTmsNotify(OrderReceiptNotifyDTO payNotify) {
        log.info("[签收单 在线支付--回调] orderReceiptPayNotifyDTO is {}", JSON.toJSONString(payNotify));

        CommonResult<JSONObject> commonResult = new CommonResult<>();

        try {

            ValidationBeanUtils.checkRequiredFields(payNotify);

            OrderSignHead orderSignHead = signOrderService.getSignHead(payNotify.getReceipt_order_id(), true);
            if (orderSignHead == null) {
                throw new BusinessException(ReturnCode.REQUEST_PARAMS_IS_NULL, "签收单不存在，请稍后再试。");
            }

            if (!OrderConcurrentHandler.lockOrder(orderSignHead.getReceiptOrderId())) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "签收单正在处理中……");
            }

            this.validate(orderSignHead);
            // 幂等
            if (orderSignHead.getPayStatus().equals(PayStatus.PAID.getValue()) && orderSignHead.getStatus() == SignStatus.ARRIVAL.getIndex()) {
                commonResult.setCode(ReturnCode.REQUEST_SUCCESS);
                commonResult.setMessage(ExceptionStatus.SUCCESS.getMessage());
                //支付完成，通知商城退款退券
                OmsEventBus.post(orderSignHead);
                return commonResult;
            }

            OrderSignHead signHead4update = initSign(orderSignHead, payNotify.getChannel_type(), payNotify.getPay_payment_no());
            OrderShippingHead shippingHead4update = initShipping(orderSignHead);
            OrderHead orderHead4update = initOrder(orderSignHead);

            boolean payFlag = this.paymentService.updatePayStatus(false, orderSignHead, orderHead4update, shippingHead4update, signHead4update);

            if (payFlag) {
                orderHead4update.setOrderCode(orderSignHead.getOrderId());
                this.notifyEs(orderHead4update, shippingHead4update, signHead4update);
                //支付完成，通知商城退款退券
                OmsEventBus.post(orderSignHead);

                omsTaskService.add35Task(Collections.singletonList(orderSignHead));
            }
            commonResult.setCode(ReturnCode.REQUEST_SUCCESS);
            commonResult.setMessage(ExceptionStatus.SUCCESS.getMessage());
        } catch (BusinessException e) {
            commonResult.setCode(e.getCode());
            commonResult.setMessage(e.getMessage());
            log.error("业务异常code : " + e.getCode() + ",异常信息: " + e.getMessage(), e);
            Exceptions.printStackTraceLineByLine(e);
        } catch (Exception e) {
            commonResult.setCode(ExceptionStatus.E3001001.getCode());
            commonResult.setMessage(ExceptionStatus.E3001001.getMessage());
            log.error("业务异常code : " + ExceptionStatus.E3001001.getCode(), e);
            Exceptions.printStackTraceLineByLine(e);
        }

        return commonResult;
    }


    private OrderShippingHead initShipping(OrderSignHead orderSignHead) {
        OrderShippingHead shippingHead = new OrderShippingHead();
        shippingHead.setShippingOrderId(orderSignHead.getShippingOrderId());
        shippingHead.setStatus(ShippingStatus.DELIVERED.getIndex());
        shippingHead.setReceiptStatus(ShippingReceiptStatus.RECEIPT.getIndex());
        shippingHead.setArrivedAt(DateUtil.getCurrentTime());
        shippingHead.setActivedAt(DateUtil.getCurrentTime());
        shippingHead.setUpdatedAt(DateUtil.getCurrentTime());

        return shippingHead;
    }

    private OrderSignHead initSign(OrderSignHead orderSignHead, String channel_type, String pay_payment_no) {
        OrderSignHead signHead = new OrderSignHead();
        signHead.setReceiptOrderId(orderSignHead.getReceiptOrderId());
        signHead.setPayStatus(PayStatus.PAID.getValue());
        signHead.setStatus(SignStatus.ARRIVAL.getIndex());
        signHead.setPayType(Integer.parseInt(channel_type));
        signHead.setUpdatedAt(DateUtil.getCurrentTime());
        signHead.setConfirmAt(DateUtil.getCurrentTime());

        JSONObject ext = JSON.parseObject(orderSignHead.getExt());
        JSONArray payNo = new JSONArray();
        payNo.add(pay_payment_no);
        ext.put("pay_payment_no", payNo);

        signHead.setExt(ext.toJSONString());

        return signHead;
    }

    private OrderHead initOrder(OrderSignHead orderSignHead) {
        OrderHead orderHead = new OrderHead();
        orderHead.setOrderCode(orderSignHead.getOrderId());
        orderHead.setOrderStatus(OrderStatus.ORDER_SIGN.getIndex());
        orderHead.setUpdateTime(DateUtil.getCurrentTime());

        return orderHead;
    }


    @POST
    @Path("notify")
    @Override
    public String payNotify(OrderReceiptPayNotifyDTO payNotify) {
        log.info("[签收单 在线支付--回调] orderReceiptPayNotifyDTO is {}", JSON.toJSONString(payNotify));

        JSONObject res = new JSONObject();
        JSONObject content = new JSONObject();
        res.put("ret", "0");

        if (!"SUCCESS".equals(payNotify.getPay_code())) {
            res.put("ret", "1000");
            content.put("return_code", "FAIL");
            return res.toJSONString();
        }

        String payTradeid = payNotify.getTrade_id();
        try {

            OrderSignHead orderSignHead = signOrderService.getSignHead(Long.valueOf(payTradeid), true);
            if (orderSignHead == null) {
                throw new BusinessException(ReturnCode.REQUEST_PARAMS_IS_NULL, "签收单不存在，请稍后再试。");
            }

            if (!OrderConcurrentHandler.lockOrder(orderSignHead.getReceiptOrderId())) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "签收单正在处理中……");
            }

            this.validate(orderSignHead);
            // 幂等
            if (orderSignHead.getPayStatus().equals(PayStatus.PAID.getValue())) {

                content.put("return_code", "SUCCESS");
                content.put("return_msg", "OK");

                res.put("content", content);
                return res.toJSONString();
            }

            OrderSignHead signHead4update = initSign(orderSignHead, payNotify.getChannel_type(), payNotify.getPay_payment_no());
            OrderShippingHead shippingHead4update = initShipping(orderSignHead);
            OrderHead orderHead4update = initOrder(orderSignHead);

            boolean payFlag = this.paymentService.updatePayStatus(true, orderSignHead, orderHead4update, shippingHead4update, signHead4update);

            if (payFlag) {
                orderHead4update.setOrderCode(orderSignHead.getOrderId());
                this.notifyEs(orderHead4update, shippingHead4update, signHead4update);

                omsTaskService.add35Task(Collections.singletonList(orderSignHead));
            }

            content.put("return_code", "SUCCESS");
            content.put("return_msg", "OK");
        } catch (BusinessException e) {
            res.put("ret", "1000");
            content.put("return_code", "FAIL");
            log.error("业务异常code : " + e.getCode() + ",异常信息: " + e.getMessage(), e);
            Exceptions.printStackTraceLineByLine(e);
        } catch (Exception e) {
            res.put("ret", "1000");
            content.put("return_code", "FAIL");
            log.error("业务异常code : " + ExceptionStatus.E3001001.getCode(), e);
            Exceptions.printStackTraceLineByLine(e);
        }

        res.put("content", content);
        return res.toJSONString();
    }

    /**
     *
     */
    private void notifyEs(OrderHead orderHead, OrderShippingHead shippingHead, OrderSignHead oderSignHead) {
        String logSign = UUID.randomUUID().toString();

        try {
            OrderHeadForEs ohEs = new OrderHeadForEs();
            ohEs.setOrderCode(orderHead.getOrderCode());
            ohEs.setOrderStatus(orderHead.getOrderStatus());
            log.info(logSign + "【ES入参修改订单】-- " + JsonUtils.obj2Json(ohEs));
            esProxy.editIndex(ohEs, logSign);

            OrderShippingHeadWithBLOBs oshEs = new OrderShippingHeadWithBLOBs();
            oshEs.setShippingOrderId(shippingHead.getShippingOrderId());
            oshEs.setStatus(shippingHead.getStatus());
            oshEs.setReceiptStatus(shippingHead.getReceiptStatus());
            log.info(logSign + "【ES入参修改发货】-- " + JsonUtils.obj2Json(oshEs));
            esProxy.editIndex(oshEs, logSign);

            log.info(logSign + "【ES入参修改签收】-- " + JsonUtils.obj2Json(oderSignHead));
            esProxy.editIndex(oderSignHead, logSign);
        } catch (Exception e) {
            log.info("签收单支付回调处理es异常", e);
        }
    }


    private void validate(OrderSignHead orderSignHead) {


    }

//    private void sendEmail(String msg, OrderReceiptPayNotifyDTO payNotify) {
//        StringBuilder sb = new StringBuilder("【警告】receipt 在线支付--回调,出现异常!! \n")
//                .append("回调参数: ")
//                .append(JSON.toJSONString(payNotify))
//                .append("\n")
//                .append("异常信息: ")
//                .append(msg);
//
//        this.sendEmail(sb.toString());
//    }


//    private void sendEmail(String msg) {
//        // 邮件报警
//        String title = "[" + system + "][receipt]";
//        String[] persons = {"aop@lsh123.com"};
//
//        OmsEventBus.post(new EmailModel(msg, title, persons));
//    }

//
//    public static void main(String[] args) {
//        OrderReceiptPayNotifyDTO dto = new OrderReceiptPayNotifyDTO();
//
//        dto.setChannel_type("2");
//        dto.setPay_code("SUCCESS");
//        dto.setPay_payment_no("6565232323112121");
//        dto.setTrade_id("1278272492839238923");
//        dto.setPayment_amount("3263.99");
//
//        System.out.printf(JSON.toJSONString(dto));
//    }
}
